<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>web shell 登录Linux远程主机</title>
    <link rel="shortcut icon" th:href="@{/static/img/favicon.ico}" />
    <link rel="stylesheet" th:href="@{/static/css/xterm.css}" />
    <link rel="stylesheet" th:href="@{/static/css/webShell.css}" />
    <script type="text/javascript" th:src="@{/static/js/xterm.js}"></script>
    <script type="text/javascript" th:src="@{/static/js/jquery-3.5.1.min.js}"></script>
    <script type="text/javascript" th:src="@{/static/js/web-socket.js}"></script>
    <script type="text/javascript" th:src="@{/static/js/crypto-js.min.js}"></script>
    <script type="text/javascript" th:src="@{/static/js/web-shell.js}"></script>
</head>
<body>
    <a href='https://gitee.com/zmzhou-star/web-shell' style="float: right;">
        <img src='https://gitee.com/zmzhou-star/web-shell/widgets/widget_1.svg' alt='Fork me on Gitee'/>
    </a>
    <div id="login" class="login">
        <h1>登录Linux远程主机</h1>
        <form action="#" onsubmit="login()">
            <input type="text" id="host" required="required" placeholder="主机IP" value="192.168.163.130"/>
            <input type="text" id="username" value="root" required="required" placeholder="用户名" />
            <input type="password" id="password" required="required" placeholder="密码"/>
            <input type="text" id="port" value="22" required="required" placeholder="端口" />
            <button class="button" type="submit">登录</button>
        </form>
        <p class="github-star">
            <a href="https://gitee.com/zmzhou-star/web-shell/stargazers">
                <img src="https://gitee.com/zmzhou-star/web-shell/badge/star.svg?theme=dark" alt="star">
            </a>
            <a href="https://gitee.com/zmzhou-star/web-shell/members">
                <img src="https://gitee.com/zmzhou-star/web-shell/badge/fork.svg?theme=dark" alt="fork">
            </a>
            <a href="https://github.com/zmzhou-star/web-shell/stargazers" target="_blank" rel="noopener">
                <img src="https://badgen.net/github/stars/zmzhou-star/web-shell?icon=github&color=4ab8a1" data-origin="https://badgen.net/github/stars/zmzhou-star/web-shell?icon=github&color=4ab8a1" alt="stars">
            </a>
            <a href="https://github.com/zmzhou-star/web-shell/members" target="_blank" rel="noopener">
                <img src="https://badgen.net/github/forks/zmzhou-star/web-shell?icon=github&color=4ab8a1" data-origin="https://badgen.net/github/forks/zmzhou-star/web-shell?icon=github&color=4ab8a1" alt="forks">
            </a>
        </p>
    </div>
    <div id="menu" class="menu" style="display: none">
        <label>菜单</label>
        <div onclick="loginSftp()">SFTP</div>
    </div>
    <div id="terminal" class="indexContainer"></div>
</body>
<script>
    // 解决第一次登录成功也跳转回登录问题
    $(document).ready(function (){
        let url = window.location.href;
        if (!url.endsWith("/?#")) {
            window.location.href = url + "?#";
        }
        let num1 = Math.round(Math.random()* 360);
        let num2 = Math.round(Math.random()* 360);
        $('body').css({background: 'linear-gradient(to left bottom, hsl(' + num1 + ', 100%, 85%) 0%,hsl(' + num2 + ', 100%, 85%) 100%)'})
    })
    // 获取容器宽高/字号大小，定义行数和列数
    let rows = document.querySelector(".indexContainer").offsetHeight / 16 - 5;
    let cols = document.querySelector(".indexContainer").offsetWidth / 9;
    let term = new Terminal({
        rendererType: "canvas", //渲染类型
        pid: 1,
        name: 'terminal',
        rows: parseInt(rows), //行数
        cols: parseInt(cols),
        convertEol: true, //启用时，光标将设置为下一行的开头
        scrollback: 500,//终端中的回滚量
        disableStdin: false, //是否应禁用输入。
        cursorStyle: 'underline', //光标样式
        cursorBlink: true, //光标闪烁
        tabStopWidth: 8, //制表宽度
        screenKeys: true, //Xterm下的快捷键
        theme: {
            foreground: '#58a6ff', //字体,LightGreen,Orange,SlateBlue,Magenta Purple Red Violet White Yellow
            background: '#2B2B2B', //背景色
            // foreground: "#7e9192", //字体
            // background: "#002833", //背景色
            cursor: "Orange", //设置光标
            lineHeight: 16
        }
    });

    term.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ ')
    // 换行并输入起始符“$”
    term.prompt = () => {
        term.write("\r\n$ ");
    };

    let client = new WebSocketClient();

    /**
     * 执行连接操作
     * @param {Object} params 连接参数
     * @param {String} divId 显示控件id
     */
    function connect(params, divId) {
        term.open(document.getElementById(divId), true);
        //在页面上显示连接中...
        term.write('\r\nConnecting...');
        //执行连接操作
        client.connect({
            onError: function (error) {
                //连接失败回调
                term.write('Error: ' + error + '\r\n');
            },
            onConnect: function () {
                //连接主机
                client.send(params);
                $("#login").hide();
                $("#menu").show();
            },
            onClose: function () {
                //连接关闭回调
                term.write("\rconnection closed");
                $("#login").show();
            },
            onData: function (data) {
                //收到数据时回调
                term.write(data);
            }
        });
        term.onData(e => {
            //键盘输入时的回调函数
            client.sendClientData(e);
        })
    }
    let params = {
        operate:'connect',
        host: '',//IP
        port: '22',//端口号
        username: '',//用户名
        password: ''//密码
    }
    // connect(params, 'terminal')

    let loginParams = {};
    function login() {
        let params = {
            operate:'connect',
            host: $("#host").val(),//IP
            port: $("#port").val(),//端口号
            username: $("#username").val(),//用户名
            password: encrypt($("#password").val())//密码
        }
        loginParams = params;
        // 修改页面标签
        document.title += " " + params.host;
        connect(params, 'terminal')
    }
    // login()
    /** 连接SFTP服务 */
    function loginSftp() {
        loginParams.operate = 'sftp'
        window.open(window.location.href.replace('?#', 'sftp?params=' + encodeURIComponent(JSON.stringify(loginParams))))
    }
    let selection;
    //选中复制
    term.onSelectionChange(function() {
        if (term.hasSelection()) {
            selection = term.getSelection();
        }
    });
    term.attachCustomKeyEventHandler(function(ev) {
        //粘贴 ctrl+v
        if (ev.keyCode === 86 && ev.ctrlKey) {
            client.sendClientData("\x00" + selection);
            selection = "";
        }
    });
    // 内容全屏显示-窗口大小发生改变时
    function resizeScreen(size) {
        console.log("size", size);
        term.scrollToBottom();
        try {
            // fitAddon.fit();
            // 窗口大小改变时触发xterm的resize方法，向后端发送行列数，格式由后端决定
            term.onResize(size => {
                client.send({ Op: "resize", Cols: cols, Rows: rows });
            });
        } catch (e) {
            console.log("e", e.message);
        }
    }

    window.addEventListener("resize", resizeScreen);
</script>
</html>
